import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Stack;

public class Calculator extends JFrame implements ActionListener {
    private JTextField display;
    private StringBuilder expression;

    public Calculator() {

        expression = new StringBuilder();


        setTitle("简易计算器(徐嘉文制作)");
        setSize(400, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭操作
        setLayout(new BorderLayout());//边界布局


        display = new JTextField();//显示区
        display.setFont(new Font("Arial", Font.PLAIN, 64));
        display.setEditable(false);//对话框不可编辑
        add(display, BorderLayout.NORTH);


        JPanel buttonPanel = new JPanel();//面板
        buttonPanel.setLayout(new GridLayout(5, 4, 10, 10));//网格布局


        String[] buttons = {
                "(", ")", "C", "<-",
                "7", "8", "9", "/",
                "4", "5", "6", "*",
                "1", "2", "3", "-",
                "0", ".", "=", "+"
        };


        for (String button : buttons) {
            JButton b = new JButton(button);
            b.setFont(new Font("Arial", Font.PLAIN, 24));
            b.addActionListener(this);
            buttonPanel.add(b);
        }


        add(buttonPanel, BorderLayout.CENTER);

        setVisible(true);
    }

    // 处理按钮点击事件
    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();

        switch (command) {
            case "C":
                expression.setLength(0);
                display.setText("");
                break;
            case "<-":
                if (expression.length() > 0) {
                    expression.deleteCharAt(expression.length() - 1);
                    display.setText(expression.toString());
                }
                break;
            case "=":
                try {
                    String result = evaluateExpression(expression.toString());
                    display.setText(result);
                    //expression.setLength(0);
                } catch (Exception ex) {
                    display.setText("Error");
                }
                break;
            default:
                expression.append(command);
                display.setText(expression.toString());
                break;
        }
    }

    // 计算后缀表达式的值
    private String evaluateExpression(String expr) throws Exception {
        String postfix = toPostfix(expr);
        return String.valueOf(evaluate(postfix));
    }

    // 将中缀表达式转换为后缀表达式
    private String toPostfix(String expr) {
        StringBuilder ans = new StringBuilder();
        Stack<Character> st = new Stack<>();

        for (int i = 0; i < expr.length(); i++) {
            char c = expr.charAt(i);

            if (Character.isDigit(c) || c == '.') {
                ans.append(c);
            } else if (c == '(') {
                st.push(c);
            } else if (c == ')') {
                while (!st.isEmpty() && st.peek() != '(') {
                    ans.append(' ').append(st.pop());
                }
                st.pop();
            } else if (isOperator(c)) {
                ans.append(' ');
                while (!st.isEmpty() && youxianji(st.peek()) >= youxianji(c)) {
                    ans.append(st.pop()).append(' ');
                }
                st.push(c);
            }
        }

        while (!st.isEmpty()) {
            ans.append(' ').append(st.pop());
        }

        return ans.toString();
    }

    // 计算后缀表达式的值
    private double evaluate(String postfix) {
        Stack<Double> stack = new Stack<>();
        String[] tokens = postfix.split("\\s+");

        for (String token : tokens) {
            if (isNumber(token)) {
                stack.push(Double.parseDouble(token));
            } else if (isOperator(token.charAt(0))) {
                double b = stack.pop();
                double a = stack.pop();
                switch (token.charAt(0)) {
                    case '+': stack.push(a + b); break;
                    case '-': stack.push(a - b); break;
                    case '*': stack.push(a * b); break;
                    case '/': stack.push(a / b); break;
                }
            }
        }

        return stack.pop();
    }

    private boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/';
    }

    private boolean isNumber(String s) {
        try {
            Double.parseDouble(s);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    private int youxianji(char op) {
        switch (op) {
            case '+':
            case '-':
                return 1;
            case '*':
            case '/':
                return 2;
            default:
                return 0;
        }
    }

    public static void main(String[] args) {
        new Calculator();
    }
}
